package stocc.converter;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import stocc.logger.Level;
import stocc.subject.*;

public class ObjectPrinter {
	public ObjectPrinter(){
		//
	}
	
	/**
	 * Outputs(prints) the given objects into individual .java files
	 * @param objects The objects to print
	 */
	public void print(List<View> objects) throws IOException{
		for(View v : objects){
			String contents = printView(v);

			// Create file 
		    FileWriter fstream = new FileWriter("output/" + v.getName() + ".java");
		    BufferedWriter out = new BufferedWriter(fstream);

		    out.write(contents);
		    //Close the output stream
		    out.close();
		}
	}
	
	private String printView(View v){
		String output = "";
		
		
		//Organize imports
		Set<String> importSet = new HashSet<String>();
		for(String s : v.getImports()){
			importSet.add(s);
		}
		
		for(String s : importSet){
			output += "import " + s + ';' + '\n';
		}
		//Print class signature
		output += 	v.getVisibility().toString().toLowerCase() + " " +
					"class" + " " +
					v.getName() + " " +
					"{";
		
		for(Member m : v.getMembers()){
			output += '\n';
			output += printMember(1, m);
		}
		
		for(Method m : v.getMethods()){
			output += '\n';
			output += printMethod(1, m);
		}
		
		output += '\n' + "}";
		
		return output;
	}
	
	private String printMethod(int indent, Method method){
		log("Adding method " + method.getName(), Level.DEBUG);
		
		String output = "";
		
		//Print method signature
		output += 	tab(indent) + 
					method.getVisibility().toString().toLowerCase() + " " +
					method.getReturnType() + " " +
					method.getName() +
					"(" +
					implode(method.getParameters(), ',') +
					")";
		
		output += '\n';
		//Print method code
		output += 	tab(indent) + "{\n" + 
					method.getCode() +
					"\n" +
					tab(indent) + "}";
					
		log("Done adding method " + method.getName(), Level.DEBUG);
		
		return output;
	}
	
	private String printMember(int indent, Member member){
		log("Adding member " + member.getName(), Level.DEBUG);
		String output = "";
		
		//Print member
		output += 	tab(indent) + 
					member.getVisibility().toString().toLowerCase() + " " +
					member.getType() + " " +
					member.getName() + 
					";";
		
		return output;
	}
	
	private String tab(int indent){
		String ret = "";
		for(int i = 0; i < indent; i++){
			ret += '\t';
		}
		return ret;		
	}
	
	private String implode(List<String> strings, char join){
		if(strings == null || strings.size() == 0){
			return "";
		}
		String ret = "";
		for(String s : strings){
			ret += s + join;
		}
		//Lazily remove last join char
		return ret.substring(0, ret.length() - 1);
	}
	/**
	 * Logging method, add this to any class that does logging
	 * @param message The message to be logged
	 * @param level The logging level of the message
	 */
	private static void log(String message, Level level){
		//stocc.logger.Logger.getLogger().log(level, "Printer", message);
	}	
}
